#ifndef _ICECODE_UTILS_PASSWD_HPP
#define _ICECODE_UTILS_PASSWD_HPP

#include <string>
#include <map>
#include <stdexcept>

namespace icecode {

  //Passwd file parser
  class PasswdFile {
  public:
    /*
      THROWS:
       std::runtime_error("Unable to open the provided passwd file")
    */
    PasswdFile(std::string path = "/etc/passwd");
    
    class User {
      std::string login, pass_hash, home, shell, name;
      unsigned long uid, gid;
      
    public:
      /*
	THROWS:
	 std::out_of_range("User name does not exist")
      */
      User(std::string login_name = "") : login(login_name) { if(login.empty()) throw std::out_of_range("User name does not exist"); }
      
#define WICE_STR_GETSET(name, var) std::string get##name() const { return var; } \
      void set##name(std::string val) { var = val; }
      
      WICE_STR_GETSET(Login, login)
      WICE_STR_GETSET(Hash, pass_hash)
      WICE_STR_GETSET(Home, home)
      WICE_STR_GETSET(Shell, shell)
      WICE_STR_GETSET(Name, name)
      
#undef WICE_STR_GETSET
      
#define WICE_ULONG_GETSET(name, var) unsigned long get##name() const { return var; } \
      void set##name(unsigned long val) { var = val; }
      
      WICE_ULONG_GETSET(UID, uid)
      WICE_ULONG_GETSET(GID, gid)
      
#undef WICE_ULONG_GETSET
      
    };
    
    /*
      THROWS:
       std::out_of_range("User name does not exist")
    */
    const PasswdFile::User& getUser(std::string login) { return const_cast<const PasswdFile::User&>(users[login]); }
    
  private:
    std::map<std::string, PasswdFile::User> users;
  };
}

#endif //_ICECODE_UTILS_PASSWD_HPP
